module shifter#(N_BIT=8)(clk, en, sel, input_x, Q);
  input clk;
  input en;
  input [2:0] sel;
  input [(N_BIT-1):0] input_x;
  output reg [(N_BIT-1):0] Q;
  always @ (posedge clk)
    if (en) begin
      case(sel)
        3'b000: Q <= 0;
	3'b001: Q <= input_x;
	3'b010: Q <= {1'b0, Q[(N_BIT-1):1]};
	3'b011: Q <= {Q[(N_BIT-2):0], 1'b0};
	3'b100: Q <= {Q[(N_BIT-1)], Q[(N_BIT-1):1]};
	3'b101: Q <= {input_x[(N_BIT-1)], Q[(N_BIT-1):1]};
	3'b110: Q <= {Q[0], Q[(N_BIT-1):1]};
	3'b111: Q <= {Q[(N_BIT-2):0], Q[(N_BIT-1)]};
      endcase
    end
endmodule

module barrelshifter#(N_BIT=8,N_MOVE=3)(LR, AL, shamt, input_x, Q);
  input LR;
  input AL;
  input [(N_MOVE-1):0] shamt;
  input [(N_BIT-1):0] input_x;
  output [(N_BIT-1):0] Q;
  wire [(N_BIT*(N_MOVE-1)-1):0] res;
  wire AL_out;
  MuxKey #(2, 1, 1) muxal(AL_out, AL, {
	  1'b0, 1'b0,
	  1'b1, input_x[N_BIT-1]
	  });
  barrelunit #(N_BIT, 1) bu1(LR, AL_out, shamt[0], input_x, res[(N_BIT-1):0]);
  barrelunit #(N_BIT, 2) bu2(LR, AL_out, shamt[1], res[(N_BIT-1):0], res[(N_BIT*2-1):N_BIT]);
  barrelunit #(N_BIT, 4) bu3(LR, AL_out, shamt[2], res[(N_BIT*2-1):N_BIT], Q);
endmodule
module barrelunit#(N_BIT=8,N_MOVE=1)(LR, AL_in, shamt, x, Q);
  input LR;
  input AL_in;
  input shamt;
  input [(N_BIT-1):0] x;
  output [(N_BIT-1):0] Q;

  genvar i;
  generate for (i=0; i<N_BIT; i=i+1) begin:move1
	  if(i<N_MOVE) begin
          MuxKey #(4, 2, 1) mux_inst(Q[i], {LR, shamt}, {
		  2'b00, x[i],
		  2'b01, x[i+N_MOVE],
		  2'b10, x[i],
		  2'b11, 1'b0
		  });
	  end
	  else if (i>=(N_BIT-N_MOVE)) begin
          MuxKey #(4, 2, 1) mux_inst(Q[i], {LR, shamt}, {
		  2'b00, x[i],
		  2'b01, AL_in,
		  2'b10, x[i],
		  2'b11, x[i-N_MOVE]
		  });
	  end
	  else
	  MuxKey #(4, 2, 1) mux_inst(Q[i], {LR, shamt}, {
		  2'b00, x[i],
		  2'b01, x[i+N_MOVE],
		  2'b10, x[i],
		  2'b11, x[i-N_MOVE]
		  });
	  end
  endgenerate
endmodule
